import { DelNode, EmphNode, MNode, ParagraphNode, StrongNode, TextNode } from "../mnodes";
import DelimitersStack from "../tnodes/delimiter-stack";

/**
 * 将字符串转换为DOM节点树
 */
export default class TransformLine {
    
    /**索引值 */
    public _offset:number = 0
    /**分隔符栈 */
    public _delimiter: DelimitersStack | null
    /**传入行  */
    public _line:string = ''
    /**DOM节点树 */
    private _mnode: MNode | null;

  
    /**
     * 普通文本正则表达式
     */
    static textReg = /^[^\[\]*_~]+/m; 
    constructor () {
        this._offset = 0;
        this._delimiter = null;
        this._line = '';
        this._mnode = null;
    }
    parse(line:string){
        this._line = line
        /* 开始遍历区分虚拟节点和分隔符栈*/
        this._delimiter = null;
        this._mnode = new ParagraphNode();
        this._line = line;
        /* 从左往右依次遍历区分*/
        this._parseLine();
        /** 匹配虚拟节点生成最终模板 */
        this._transNormal();
    
        return this._mnode;
    }

    /* 从左往右依次遍历区分*/
    _parseLine (): void {
        let char: string = '';
        while (char = this._line[this._offset]) {
            switch (char) {
                case '*':
                case '_':
                case '~':
                /**特殊字符 */
                this._parseNormal(char);
                default:
                /**普通文本 */
                this._parseText();
            }
        }
    }

    _parseText (): void {
        const matchText: string | null = this._match(TransformLine.textReg);
        if (matchText) {
            this._mnode?.appendChild(new TextNode(matchText));
        }
    }

    /**文本节点匹配 */
    _match (reg: RegExp): string | null {
        const matched = reg.exec(this._line.slice(this._offset));
        if (matched) {
            this._offset += matched[0].length;
            return matched[0];
        } else {
            return null;
        }
    }

    /** 特殊字符 */
    _parseNormal (char: string): void {
        let count: number = 0;
        let startPos: number = this._offset;
        while (this._line[this._offset] === char) {
          count++;
          this._offset++;
        }
        /** 插入虚拟节点 */
        const textNode: TextNode = new TextNode(this._line.substr(startPos, count));
        this._mnode?.appendChild(textNode);
        /** 生成分隔符节点 */
        const delimiter: DelimitersStack = new DelimitersStack(char, count, textNode);
        if (this._delimiter) {
          this._delimiter.next = delimiter;
          delimiter.prev = this._delimiter;
        }
        this._delimiter = delimiter;
    }

    /** 匹配虚拟节点生成最终模板 */
    _transNormal() {
        let closer: DelimitersStack | null = this._delimiter;
        let opener: DelimitersStack | null = null;
    
        /** 获取head */
        while (closer != null && closer.prev != null) {
          closer = closer.prev;
        }
    
        while (closer) {
          const char: string = closer.char;
          /**获取特殊字符 */
          if (char === '*' || char === '_' || char === '~') {
              /**匹配是否有对应的open */
              opener = this._transNormalOpener(closer);
              if (opener) {
                  /** 记录匹配消耗的字符 */
                  let usedCount = 0; 
                  const openerNode: TextNode = opener.mnode;
                  const closerNode: TextNode = closer.mnode;
                  /** 特殊字符生成的不同节点 */
                  let transNode: MNode | null = null; 
                  
                  if (char === '*' || char === '_') {
                      if (opener.currentCount >= 2 && closer.currentCount >= 2) {
                          transNode = new StrongNode();
                          usedCount = 2;
                      } else {
                          transNode = new EmphNode();
                          usedCount = 1;
                      }
                  } else {
                      usedCount = 1;
                      transNode = new DelNode();
                  }
    
                  /** 消耗的字符 */
                  opener.currentCount -= usedCount;
                  openerNode.text = openerNode.text.slice(usedCount);
    
                  closer.currentCount -= usedCount;
                  closerNode.text = closerNode.text.slice(usedCount);
    
                  /** 包裹匹配到节点的内容 */
                  let betweenNode: MNode | null = openerNode.next;
                  let next;
                  while (betweenNode && betweenNode !== closerNode) {
                      next = betweenNode.next;
                      transNode.appendChild(betweenNode);
                      betweenNode = next;
                  }
    
                  /** 将匹配到的内容插入虚拟节点树 */
                  openerNode.insertAfter(transNode);
                  /** 删除分隔符节点内容 */
                  DelimitersStack.delBetween(opener, closer);
                  if (opener.currentCount === 0) {
                      opener.remove();
                      openerNode.unlink();
                  }
    
                  if (closer.currentCount === 0) {
                      /**closer后移，防止后续pre寻找对应的open */
                      const nextCloser = closer.next;
                      if (this._delimiter === closer) {
                          this._delimiter = closer.prev;
                      }
                      closer.remove();
                      closer = nextCloser;
                      closerNode.unlink();
                  }
              } else {
                  /**未找到匹配的open,继续往下next */
                  closer = closer.next;
              }
          } else {
              closer = closer.next;
          }
        }
    }

    /**匹配是否有对应的open */
    _transNormalOpener (closer: DelimitersStack): DelimitersStack | null {
        /**往前寻找对应的open */
        let opener: DelimitersStack | null = closer.prev;
        while (opener && opener != null) {
            if (opener.char === closer.char) {
                return opener;
            } else {
                opener = opener.prev;
            }
        }
        return null;
    }
}